package com.jh.controller;

import com.jh.base.BusinessException;
import com.jh.base.ParameterException;
import com.jh.base.RepStatusCode;
import com.jh.base.ResultEntity;
import com.jh.model.IconStoreroom;
import com.jh.util.*;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.junit.platform.commons.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Encoder;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;

/**
 * 图片上传以及回显  base64
 */
//@RestController("/manage/Icon")
@RestController
@RequestMapping("/manage/Icon")
public class FileUploadController {


    private static Logger logger = LoggerFactory.getLogger(FileUploadController.class);


    @Value("${file.icon.path}")
    private String path;

//    InputStream inputStream = null;
//    byte[] data = null;
//        try {
//        inputStream = new FileInputStream(imgPath);
//        data = new byte[inputStream.available()];
//        inputStream.read(data);
//        inputStream.close();
//    } catch (
//    IOException e) {
//        e.printStackTrace();
//    }
//    // 加密
//    BASE64Encoder encoder = new BASE64Encoder();
//        return encoder.encode(data);

    /**
     * @Description 把base64字符串转换成图片文件保存, 并返回url接口
     * 前端已经将图片转成了base64位的字符串 iconStoreroom.getIconUrl()[已经是将图片转成了base64位字符串]  一般情况下是这样
     * 因为本项目没有前端  我们使用下面一个方法进行测试
     */
    @ResponseBody
    @RequestMapping(value = "/saveBase64File", method = RequestMethod.POST)
    public ResultEntity saveBase64File(@RequestBody IconStoreroom iconStoreroom) {
        ResultEntity resultEntity = new ResultEntity();
        String iconAbsolutePath = YmlUtils.getCommonYml("file.icon.path") + "";
        String iconName = UUID.randomUUID().toString();
        String suffixName = iconStoreroom.getSuffixName();
        if (StringUtils.isBlank(suffixName)) {
            iconStoreroom.setSuffixName(".png");
        }
        if (StringUtils.isBlank(iconStoreroom.getIconUrl())) {
            throw new ParameterException("请选择上传的文件");
        }
        //返回的路径存储到数据库  (将base64文件解析并且存储到文件夹中)
        String path = ImgUtil.base64ToImg(iconStoreroom.getIconUrl(), iconName, iconAbsolutePath, iconStoreroom.getSuffixName());
        String iconUrl = "/manage/Icon/getIcon?newFileName=" + iconName + iconStoreroom.getSuffixName();

        resultEntity.setData(iconUrl);

        return resultEntity;
    }

    /**
     * @Description 把base64字符串转换成图片文件保存, 并返回url接口
     * 上传图片
     */
    @ResponseBody
    @RequestMapping(value = "/toSaveBase64Photo", method = RequestMethod.POST)
    public ResultEntity toSaveBase64Photo() {

        //以下将图片转换成base64位字符串
        //磁盘中存在的文件（注意我这里是磁盘中存在的文件）
        //"C:\Users\Administrator\Desktop\图片\icon\0a55f653-ae01-49cb-835e-35be7b7b6a03.png"
//        String imgPath = "C:" + File.separator + "Users" + File.separator + "Administrator" + File.separator + "Desktop" + File.separator + "图片" + File.separator + "icon" + File.separator + "0a55f653-ae01-49cb-835e-35be7b7b6a03.png";
        //C:\Users\Dell 7050\Pictures\Screenshots
        String imgPath = "C:" + File.separator + "Users" + File.separator + "Dell 7050" + File.separator + "Pictures" + File.separator + "Screenshots" + File.separator + "2023-03-20_195446.png";

        IconStoreroom iconStoreroom = new IconStoreroom();
        InputStream inputStream = null;
        byte[] data = null;
        try {
            inputStream = new FileInputStream(imgPath);
            data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
        } catch (
                IOException e) {
            e.printStackTrace();
        }
        // 加密
        BASE64Encoder encoder = new BASE64Encoder();
        //根据输入流将图片转成base64位字符串
        String encode = encoder.encode(data);


        ResultEntity resultEntity = new ResultEntity();
        String iconAbsolutePath = YmlUtils.getCommonYml("file.icon.path") + "";
        String iconName = UUID.randomUUID().toString();
        iconStoreroom.setSuffixName(".png");
        //返回的路径存储到数据库 (将base64文件解析并且存储到文件夹中 将前端传过来的base64位文件解析并存储到文件夹中)
        String path = ImgUtil.base64ToImg(encode, iconName, iconAbsolutePath, iconStoreroom.getSuffixName());
        String iconUrl = "/manage/Icon/getIcon?newFileName=" + iconName + iconStoreroom.getSuffixName();
        resultEntity.setData(iconUrl);
        return resultEntity;
    }


    @ResponseBody
    @RequestMapping(value = "/toSaveBase64File", method = RequestMethod.POST)
    public ResultEntity toSaveBase64File(@RequestBody IconStoreroom iconStoreroom) {

        //以下将图片转换成base64位字符串
        //磁盘中存在的文件（注意我这里是磁盘中存在的文件）
        String FilePath = "C:" + File.separator + "Users" + File.separator + "Administrator" + File.separator + "Desktop" + File.separator + "1" + File.separator + "activiti.docx";
        InputStream inputStream = null;
        byte[] data = null;
        try {
            inputStream = new FileInputStream(FilePath);
            data = new byte[inputStream.available()];
            inputStream.read(data);
            inputStream.close();
        } catch (
                IOException e) {
            e.printStackTrace();
        }
        // 加密
        BASE64Encoder encoder = new BASE64Encoder();
        //将文件转换成base64位字符串
        String encode = encoder.encode(data);
        ResultEntity resultEntity = new ResultEntity();
        String iconAbsolutePath = YmlUtils.getCommonYml("file.icon.path") + "";
        String iconName = UUID.randomUUID().toString();
        //返回的路径存储到数据库 (将base64文件解析并且存储到文件夹中)
        String path = ImgUtil.base64ToImg(encode, iconName, iconAbsolutePath, iconStoreroom.getSuffixName());
        String iconUrl = "/manage/Icon/getIcon?newFileName=" + iconName + iconStoreroom.getSuffixName();
        resultEntity.setData(iconUrl);
        return resultEntity;
    }

    /**
     * @Description 图片下载接口，  post请求图片下载
     **/
    @RequestMapping(value = "/getIcon", method = {RequestMethod.GET, RequestMethod.POST})
    public ResponseEntity<byte[]> getFile(HttpServletRequest request, HttpServletResponse response) {

        String fileName = request.getParameter("newFileName");

        if (fileName != null) {
            String a[] = {"../", "/etc", " ", ":"};
            for (String t : a) {
                if (fileName.contains(t)) {
                    throw new BusinessException("非法文件");
                }
            }
        }

        File file = new File(YmlUtils.getCommonYml("file.icon.path") + File.separator + fileName);
        if (!file.exists()) {
            throw new ParameterException("照片丢失");
        }
        InputStream is = null;
        byte[] body = null;
        try {

            String downloadFileName = URLEncoder.encode(fileName, "UTF-8");
            is = new FileInputStream(file);
            body = new byte[is.available()];
            is.read(body);
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", "attchement;filename=" + downloadFileName);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            HttpStatus statusCode = HttpStatus.OK;
            ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode);
            return entity;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * @Description 图片下载接口，可用作回显  no.2
     **/
    @RequestMapping(value = "/getIconData", method = {RequestMethod.GET, RequestMethod.POST})
    public void getFileNo2(HttpServletRequest request, HttpServletResponse response) {

//        File file = new File("C:\\Users\\Administrator\\Pictures\\QQplayerPic\\%3A%5CUsers%5CAdministrator%5CPictures%5CQQplayerPic%5C57427fc8-d2ec-4569-8d75-589cea27d870.png");
//        if (!file.exists()) {
//            throw new ParameterException("照片丢失");
//        }
        try {
            // 指定要读取文件的缓冲输入字节流
            BufferedInputStream ins = new BufferedInputStream(new FileInputStream("G:\\icon\\bd00b55b-a147-4139-aeca-f18f18fc5e65.png"));
//            BufferedInputStream ins = new BufferedInputStream(new FileInputStream("G:\\menhu\\信用评级补充需求.docx"));
//                    FileImageInputStream ins = new FileImageInputStream(new File(YmlUtils.getCommonYml("file.defaultphoto.path").toString()));
            // 指定要写入文件的缓冲输出字节流
//                    BufferedOutputStream outs = new BufferedOutputStream(new FileOutputStream(file));
            OutputStream outs = response.getOutputStream();
            byte[] bb = new byte[1024];// 用来存储每次读取到的字节数组
            int n;// 每次读取到的字节数组的长度
            while ((n = ins.read(bb)) != -1) {
                outs.write(bb, 0, n);// 写入到输出流
            }
            ins.close();
            outs.flush();// 关闭流
        } catch (Exception e) {
            e.printStackTrace();
        }/*finally{
            try {
                response.getOutputStream().flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }*/

    }


    /**
     * 解决图片转成输出流  下载回显后不能打开的问题
     *
     * @param fileurl
     * @param request
     * @param response
     * @throws UnsupportedEncodingException
     */
    @RequestMapping(value = "/downloadImage")
    public void downloadImage(String fileurl, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
//        String fileName = URLDecoder.decode(fileurl, "UTF-8");

//        String suffix = fileName.substring(fileName.lastIndexOf("."));
        String suffix = "123.jpg";

        File file = new File("C:\\Users\\Administrator\\Pictures\\QQplayerPic\\%3A%5CUsers%5CAdministrator%5CPictures%5CQQplayerPic%5C57427fc8-d2ec-4569-8d75-589cea27d870.png");// //1.获取要下载的文件的绝对路径

//        String newDname = "new" + getDate() + suffix; //2.获取要下载的文件名
        String newDname = "new" + suffix; //2.获取要下载的文件名

        if (file.exists()) { //判断文件父目录是否存在

            response.reset();

            response.setHeader("content-type", "application/octet-stream");

            response.setContentType("image/jpg");

            response.setHeader("Content-Disposition", "attachment;filename=" + newDname); //3.设置content-disposition响应头控制浏览器以下载的形式打开文件
//            response.setHeader("Content-Disposition", "attachment;filename=" +  URLEncoder.encode(newDname, "UTF-8"));

            BufferedInputStream bis = null;

            OutputStream os = null;

            try {
                bis = new BufferedInputStream(new FileInputStream(file)); //4.根据文件路径获取要下载的文件输入流

                os = response.getOutputStream(); //6.通过response对象获取OutputStream流

                IOUtils.copy(bis, os);

            } catch (IOException e) {
                e.printStackTrace();

            } finally {
                if (bis != null) {
                    try {
                        bis.close();

                    } catch (IOException e) {
                        e.printStackTrace();

                    }
                }
            }
        }
    }

    /**
     * 使用UploadConfig配置类访问图片路径   接口的方式获取图片
     */
    @RequestMapping(value = "/getImage")
    public List<String> getImage(HttpServletRequest request, String jpgName) {
        // 网络协议
        String networkProtocol = request.getScheme();
        // 网络ip
        String ip = request.getServerName();
        // 端口号
        int port = request.getServerPort();
        // 项目发布名称
        String webApp = request.getContextPath();
        String urlPrefix = networkProtocol + "://" + ip + ":" + port + webApp;
        System.out.println(urlPrefix);

        String icon = path.substring(path.lastIndexOf("icon"));
        String viewPath = urlPrefix + "/" + icon + "/" + jpgName;
        String viewPathData = urlPrefix + File.separator + icon + File.separator + jpgName;
        List<String> list = new ArrayList<>();
        list.add(viewPath);
        list.add(viewPathData);
        return list;

//        return null;
    }


    /**
     * springboot读取resource下文件  即使打成jar包也可以访问jar包中的文件
     */
    @RequestMapping(value = "/TestResource")
    public void TestResource(HttpServletResponse response) throws IOException {
//        ClassPathResource classPathResource = new ClassPathResource("jpg/defaultphoto.jpg");
//        InputStream inputStream =classPathResource.getInputStream();

        System.out.println("我进来了");

        InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("jpg/defaultphoto.jpg");

        response.reset();
        response.setHeader("content-type", "application/octet-stream");
        response.setContentType("image/jpg");
        //1.设置content-disposition响应头控制浏览器以下载的形式打开文件
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("report.jpg", "UTF-8"));
        BufferedInputStream bis = null;
        OutputStream os = null;
        try {
            //2.根据文件路径获取要下载的文件输入流
            bis = new BufferedInputStream(inputStream);
            //3.通过response对象获取OutputStream流
            os = response.getOutputStream();
            IOUtils.copy(bis, os);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 多文件上传
     */
    @RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
    public ResultEntity<Map<String, Object>> uploadFiles(@RequestParam("files") MultipartFile[] files) {
        ResultEntity<Map<String, Object>> resultEntity = new ResultEntity<>();
        Map<String, Object> mapResult = new HashMap<>(5);
        if (files.length > 5) {
            return new ResultEntity<>(RepStatusCode.ILLEGAL_PARAMETER_ERROR, "上传文件不得多于5个");
        }
        // 判断files数组不能为空并且长度大于0
        if (files.length > 0) {
            // 项目在容器中实际发布运行的根路径
            String realPath = Objects.requireNonNull(YmlUtils.getCommonYml("file.upload.path"), "无法获取上传文件路径").toString();
            // 循环上传的文件
            for (MultipartFile file : files) {
                // 文件原名称
                String fileName = file.getOriginalFilename();
                // 文件类型
                String type = fileName.contains(".")
                        ? fileName.substring(fileName.lastIndexOf(".") + 1) : null;
                // 图片文件类型
                if (type != null) {
                    if ("GIF".equals(type.trim().toUpperCase()) || "PNG".equals(type.toUpperCase())
                            || "JPG".equals(type.toUpperCase()) || "JPEG".equals(type.toUpperCase())
                            || "DOC".equals(type.trim().toUpperCase()) || "DOCX".equals(type.trim().toUpperCase())
                            || "XLS".equals(type.trim().toUpperCase()) || "XLSX".equals(type.trim().toUpperCase())
                            || "PDF".equals(type.trim().toUpperCase())) {
                        // 自定义的文件名称
                        String trueFileName = UUIDUtil.getUUID() + "." + type;
                        // 设置存放图片文件的路径(年月划分)
                        String imgPath = File.separator + DateUtils.getNowYear() + File.separator
                                + DateUtils.getNowMonth() + File.separator + trueFileName;
                        mapResult.put(imgPath, fileName);

                        String path = realPath + imgPath;

                        // 创建文件夹
                        if (!Tools.createFilePath(path)) {
                            new ResultEntity(RepStatusCode.BUSINESS_ERROR, "文件夹创建失败");
                        }

                        try {
                            // 转存文件到指定的路径
                            file.transferTo(new File(path));
                        } catch (Exception e) {
                            e.printStackTrace();
                            logger.error("上传文件异常" + e.getMessage());
                        }
                    } else {
                        return new ResultEntity<>(RepStatusCode.ILLEGAL_PARAMETER_ERROR, "请选择正确格式的上传文件");
                    }
                } else {
                    return new ResultEntity<>(RepStatusCode.ILLEGAL_PARAMETER_ERROR, "上传文件不合法");
                }
            }
        } else {
            return new ResultEntity<>(RepStatusCode.ILLEGAL_PARAMETER_ERROR, "请选上传文件");
        }
        logger.info("mapResult:{}", mapResult);
        resultEntity.setData(mapResult);
        return resultEntity;
    }

    /**
     * 不可用
     * 根据文件路径，以流的方式得文件
     *
     * @param path         文件路径
     * @param httpResponse httpResponse
     * @author: wangyk
     */
    @RequestMapping(value = "/getFile")
    public void getImg(String path, HttpServletResponse httpResponse) {
        //防止目录遍历漏洞
        if (path != null) {
            String a[] = {"../", "/etc", " ", ":"};
            for (String t : a) {
                if (path.contains(t)) {
                    throw new BusinessException("非法文件");
                }
            }
        }
        //路径
        String url = (String) YmlUtils.getCommonYml("file.upload.path");
        String realPath = Objects.requireNonNull(url, "无法获取上传文件路径").toString();

        File file = new File(realPath + File.separator + path);
        FileInputStream fis = null;
        try {
            httpResponse.setContentType("image/gif");
            OutputStream out = httpResponse.getOutputStream();
            fis = new FileInputStream(file);
            byte[] b = new byte[fis.available()];

            fis.read(b);
            out.write(b);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 图片
     * 根据图片路径，以流的方式得图片
     *
     * @param path         图片路径
     * @param httpResponse httpResponse
     * @author: wangyk
     */
    @RequestMapping(value = "/getImgByPath")
    public void getImgByPath(String path, HttpServletResponse httpResponse) {
        //防止目录遍历漏洞
        if (path != null) {
            String a[] = {"../", "/etc", " ", ":"};
            for (String t : a) {
                if (path.contains(t)) {
                    throw new BusinessException("非法文件");
                }
            }
        }
        //路径
        String url = (String) YmlUtils.getCommonYml("file.icon.path");
        String realPath = Objects.requireNonNull(url, "无法获取上传文件路径").toString();

        File file = new File(realPath + File.separator + path);
        FileInputStream fis = null;
        try {
            httpResponse.setContentType("image/gif");
            OutputStream out = httpResponse.getOutputStream();
            fis = new FileInputStream(file);
            byte[] b = new byte[fis.available()];

            fis.read(b);
            out.write(b);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 查看文件详情
     * http://localhost:8802/manage/Icon/view?filepath=G://icon//bd00b55b-a147-4139-aeca-f18f18fc5e65.png
     * http://localhost:8802/manage/Icon/view?filepath=G://menhu//IERS-文件扫描方式接口文档 V1.0.0.pdf
     *
     * 浏览器本身不支持打开docx  需要安装插件,才能在线预览
     * http://localhost:8802/manage/Icon/view?filepath=G://menhu//信用评级补充需求.docx
     */
    @RequestMapping(value = "/view")
    public void view(String filepath, HttpServletResponse response) {
        if (Objects.isNull(filepath)) {
            logger.error("文件详情不存在");
        }
        try {
            FileUtils.writeBytes(filepath, response.getOutputStream());
        } catch (IOException e) {
            logger.error("文件读取异常", e);
        }
    }


    /**
     * http://localhost:8802/manage/Icon/down?filepath=G://icon//&filename=bd00b55b-a147-4139-aeca-f18f18fc5e65.png
     * http://localhost:8802/manage/Icon/down?filepath=G://menhu//&filename=IERS-%E6%96%87%E4%BB%B6%E6%89%AB%E6%8F%8F%E6%96%B9%E5%BC%8F%E6%8E%A5%E5%8F%A3%E6%96%87%E6%A1%A3%20V1.0.0.pdf
     * 文件下载
     */
    @GetMapping(value = "down")
    public void down(String filepath, String filename, HttpServletResponse response) {

        try {
            //下载
            InputStream inputStream = new BufferedInputStream(new FileInputStream(filepath + filename));
            byte[] bytes = new byte[inputStream.available()];
            inputStream.read(bytes);
            inputStream.close();

            //清空response
            response.reset();

            //二进制
            response.setContentType("application/octet-stream;charset=UTF-8");
            String fileName = new String(filename.getBytes("UTF-8"), "iso8859-1");

            //设置名称
            response.setHeader("content-disposition", "attachement;filename=" + fileName);

            //写入
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(bytes);
            outputStream.flush();
            outputStream.close();

        } catch (IOException e) {
            logger.error("文件下载异常", e);
        }
    }

}